package com.ninth_group.service.Impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.ninth_group.constant.CityQueryConstants;
import com.ninth_group.dao.CityDao;
import com.ninth_group.mapper.CityMapper;
import com.ninth_group.dto.CityDTO;
import com.ninth_group.exception.city.CityException;
import com.ninth_group.po.City;
import com.ninth_group.po.CityInfo;
import com.ninth_group.service.CityService;
import com.ninth_group.utils.CityInfoUtil;
import com.ninth_group.utils.HiveUtil;
import com.ninth_group.utils.RedisSerializerUtil;
import com.ninth_group.vo.CityVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;


@Service
public class CityServiceImpl implements CityService {
    @Resource
    private CityDao cityDao;
    @Resource
    private HiveUtil hiveUtil;
    @Resource
    private RedisSerializerUtil redisSerializerUtil;

    /**
     * 根据城市编码获取城市基本信息
     *
     * @param cityDTO 城市DTO
     * @return 城市基本信息
     */
    @Override
    public CityVO getCityBaseInfo(CityDTO cityDTO) throws JsonProcessingException {
        if (cityDTO == null || cityDTO.getProvinceName().isEmpty()
                || cityDTO.getProvinceName() == null
                || cityDTO.getCityName().isEmpty()
                || cityDTO.getCityName() == null)
            throw new CityException("省份名称或城市名称为空");

        // 1. 根据cityDTO查询城市id
        String provinceName = cityDTO.getProvinceName();
        String cityName = cityDTO.getCityName();

        // 1.2 查询redis中所有城市信息
        Set<CityInfo> cityInfo = redisSerializerUtil.get(
                CityQueryConstants.ALL_CITY_INFO,
                new TypeReference<>() {});

        Set<CityInfo> ci = null;

        // 1.3 如果没有, 查询数据库并添加到redis中
        if (cityInfo == null || cityInfo.isEmpty()) {
            ci = CityInfoUtil.getCityInfo(hiveUtil);

            redisSerializerUtil.set(CityQueryConstants.ALL_CITY_INFO, ci,
                    CityQueryConstants.CACHE_TIME, TimeUnit.MINUTES);
        }
        // 1.4 如果有, 则使用redis中的数据
        else ci = cityInfo;

        // 1.5 根据城市id查询城市信息
        List<String> cityIds = CityInfoUtil.getCityIds(ci, provinceName, cityName, hiveUtil);

        if (cityIds == null || cityIds.isEmpty()) throw new CityException("城市不存在");

        String cityId = cityIds.getFirst();

        // 2. 查询前先查看redis中是否有数据
        CityVO cityVO = redisSerializerUtil.get(cityId, CityVO.class);

        // 3. 如果有，则直接返回
        if (cityVO != null) return cityVO;

        // 3.1 如果没有，则查询数据库并添加到redis中
        City city = cityDao.getCityBaseInfo(cityIds);

        // 使用mapstruct效率比hutool的beanutils高
        CityVO vo = CityMapper.INSTANCE.toVo(city);

        redisSerializerUtil.set(cityId, vo,
                CityQueryConstants.CACHE_TIME, TimeUnit.MINUTES);
        return vo;
    }

    private List<String> getCityIds(String provinceName, String cityName) {
        Set<CityInfo> cityDataIncludingProvince =
                CityInfoUtil.getCityDataIncludingProvince(hiveUtil);
        if (cityDataIncludingProvince.isEmpty())
            return null;

        List<String> matchedCityIds = cityDataIncludingProvince.stream()
                .filter(ci -> ci.getProvince()
                        .equals(provinceName) && ci.getCity().equals(cityName))
                .map(CityInfo::getCityId)
                .toList();

        if (matchedCityIds.isEmpty())
            return null;

        return matchedCityIds;
    }

}
